﻿#include "db_api_.h"

#define head_reserved	3

typedef struct rs_filter{
	char* p;
	int type;
	int like;
}rs_filter;

typedef int (*cb_filter)(const RECORD * rec, rs_filter filter, INDEX * idx);

int is_album_in_file(const char * album, int ofs)
{
	INDEX idx;
	int ret = 0;
	int res = FR_OK;
	unsigned int br = sizeof(INDEX);
	unsigned long long old = f_tell(hDB->f_index);
	f_lseek(hDB->f_index, ofs);
	while(res == FR_OK && br == sizeof(INDEX))
	{
		res = f_read(hDB->f_index, &idx, sizeof(INDEX), &br);
		if(res == FR_OK && br == sizeof(INDEX))
		{
			if(strcmp(album, idx.name)==0)//memcmp
			{
				ret = 1;
				break;
			}
		}
	}
	f_lseek(hDB->f_index, old);
	assert(f_tell(hDB->f_index) == f_size(hDB->f_index));
	return ret;
}

int is_artist_in_file(const char * artist, int ofs)
{
	INDEX idx;
	int ret = 0;
	int res = FR_OK;
	unsigned int br = sizeof(INDEX);
	unsigned long long old = f_tell(hDB->f_index);
	f_lseek(hDB->f_index, ofs);
	while(res == FR_OK && br == sizeof(INDEX))
	{
		res = f_read(hDB->f_index, &idx, sizeof(INDEX), &br);
		if(res == FR_OK && br == sizeof(INDEX))
		{
			if(strcmp(artist, idx.name)==0)//memcmp
			{
				ret = 1;
				break;
			}
		}
	}
	f_lseek(hDB->f_index, old);
	assert(f_tell(hDB->f_index) == f_size(hDB->f_index));
	return ret;
}

int _build_field_(cb_filter cb, rs_filter filter)
{
	int res = 0;
	unsigned int br = sizeof(RECORD);
	RECORD rec;
	INDEX idx = {0};
	int cnt=0;
	res += f_lseek(hDB->f_record, 0);
	while(res == FR_OK && br == sizeof(RECORD))
	{
		res += message_pump(hDB->state);	if(res)break;if(hDB->state != 3)break;

		res += f_read(hDB->f_record, &rec, sizeof(RECORD), &br);
		if(res == FR_OK && br == sizeof(RECORD))
		{
			if(cb(&rec, filter, &idx))
			{
				unsigned int bw;
				res += f_lseek(hDB->f_index, f_size(hDB->f_index));
				res += f_write(hDB->f_index, &idx, sizeof(INDEX), &bw);
				if(res == FR_OK && bw == sizeof(INDEX))
				{
					cnt++;
				}
			}
		}
	}
	return cnt;
}

int build_type_field()
{
	int i;
	int res = 0;
	unsigned int br;
	INDEX idx = {"",0,4,4,0};

	res += message_pump(hDB->state);	if(hDB->state != 3)return res;

	hDB->index_field[0].offset = (int)f_size(hDB->f_index);

	res += f_lseek(hDB->f_index, f_size(hDB->f_index));

	strcpy(idx.name, "type text");
	idx.reserved = 4;
	idx.total = 4;
	res += f_write(hDB->f_index, &idx, sizeof(INDEX), &br);

	strcpy(idx.name, "type image");
	idx.reserved = 4;
	idx.total = 4;
	res += f_write(hDB->f_index, &idx, sizeof(INDEX), &br);

	strcpy(idx.name, "type audio");
	idx.reserved = 4;
	idx.total = 4;
	res += f_write(hDB->f_index, &idx, sizeof(INDEX), &br);

	strcpy(idx.name, "type video");
	idx.reserved = 4;
	idx.total = 4;
	res += f_write(hDB->f_index, &idx, sizeof(INDEX), &br);

	strcpy(idx.name, "type wave");
	idx.reserved = 1024;
	idx.total = 1024;
	res += f_write(hDB->f_index, &idx, sizeof(INDEX), &br);

	hDB->index_field[0].used = 5;
	hDB->index_field[0].reserved = 4;
	hDB->index_field[0].total = hDB->index_field[0].used + hDB->index_field[0].reserved;

	for(i=0; i<hDB->index_field[0].reserved; i++)
	{
		sprintf(idx.name, "type reserved %d", i);
		idx.reserved = 4;
		idx.total = 4;
		res += f_write(hDB->f_index, &idx, sizeof(INDEX), &br);
	}
	return res;
}
int build_like_field()
{
	int i;
	int res = 0;
	unsigned int br;
	INDEX idx = {"",0,1024,1024,0};

	res += message_pump(hDB->state);	if(hDB->state != 3)return res;

	hDB->index_field[1].offset = (int)f_size(hDB->f_index);
	
	res += f_lseek(hDB->f_index, f_size(hDB->f_index));

	for(i=1; i<=32; i++)
	{
		sprintf(idx.name, "like %d", i);
		res += f_write(hDB->f_index, &idx, sizeof(INDEX), &br);
	}

	hDB->index_field[1].used = 32;
	hDB->index_field[1].reserved = 4;
	hDB->index_field[1].total = hDB->index_field[1].used + hDB->index_field[1].reserved;

	for(i=0; i<hDB->index_field[1].reserved; i++)
	{
		sprintf(idx.name, "like reserved %d", i);
		res += f_write(hDB->f_index, &idx, sizeof(INDEX), &br);
	}
	return res;
}
int cb_folder_field(const RECORD * rec, rs_filter filter, INDEX * idx)
{
	if(rec->flag == 1)
		return 0;
	if((filter.type & rec->type) == 0)
		return 0;

	strcpy(idx->name, rec->path);
	idx->used = 0;
	if (0== dircmp(rec->path, WAVEROOT))
	{
		idx->reserved = 1024;
	}
	else
	{
		idx->reserved = 4;
	}
	idx->total = 4;
	idx->offset = 0;

	return 1;
}
int build_folder_field()
{
	int i;
	int res = 0;
	unsigned int br;
	INDEX idx = {"",0,4,4,0};
	rs_filter filter = {0, MEDIA_HI_FOLDER, 0};

	hDB->index_field[2].offset = (int)f_size(hDB->f_index);
	
	res += f_lseek(hDB->f_index, f_size(hDB->f_index));

	hDB->index_field[2].used = _build_field_(cb_folder_field, filter);	if(hDB->state != 3)return res;
	hDB->index_field[2].reserved = 4;
	hDB->index_field[2].total = hDB->index_field[2].used + hDB->index_field[2].reserved;

	for(i=0; i<hDB->index_field[2].reserved; i++)
	{
		sprintf(idx.name, "folder reserved %d", i);
		res += f_write(hDB->f_index, &idx, sizeof(INDEX), &br);
	}
	return res;
}
int build_pl_field()
{
	int i;
	int res = 0;
	unsigned int br;
	INDEX idx = {"",0,4,4,0};
	rs_filter filter = {0, MEDIA_HI_FOLDER, 0};

	hDB->index_field[3].offset = (int)f_size(hDB->f_index);
	
	res += f_lseek(hDB->f_index, f_size(hDB->f_index));

	hDB->index_field[3].used = _build_field_(cb_folder_field, filter);	if(hDB->state != 3)return res;
	hDB->index_field[3].reserved = 4;
	hDB->index_field[3].total = hDB->index_field[3].used + hDB->index_field[3].reserved;

	for(i=0; i<hDB->index_field[3].reserved; i++)
	{
		sprintf(idx.name, "folder reserved %d", i);
		res += f_write(hDB->f_index, &idx, sizeof(INDEX), &br);
	}
	return res;
}
int cb_album_field(const RECORD * rec, rs_filter filter, INDEX * idx)
{
	if(rec->flag == 1)
		return 0;
	if((filter.type & rec->type) == 0)
		return 0;
	if(rec->album[0] == 0)
		return 0;
	if(is_album_in_file(rec->album, filter.like))
		return 0;

	memcpy(idx->name, rec->album, sizeof(rec->album));
	idx->used = 0;
	idx->reserved = 4;
	idx->total = 4;
	idx->offset = 0;

	return 1;
}
int build_album_field()
{
	int i;
	int res = 0;
	unsigned int br;
	INDEX idx = {"",0,4,4,0};
	rs_filter filter = {0, MEDIA_HI_AUDIO, (int)f_size(hDB->f_index)};

	hDB->index_field[4].offset = (int)f_size(hDB->f_index);
	
	res += f_lseek(hDB->f_index, f_size(hDB->f_index));

	hDB->index_field[4].used = _build_field_(cb_album_field, filter);	if(hDB->state != 3)return res;
	hDB->index_field[4].reserved = 4;
	hDB->index_field[4].total = hDB->index_field[4].used + hDB->index_field[4].reserved;

	for(i=0; i<hDB->index_field[4].reserved; i++)
	{
		sprintf(idx.name, "album reserved %d", i);
		res += f_write(hDB->f_index, &idx, sizeof(INDEX), &br);
	}
	return res;
}
int cb_artist_field(const RECORD * rec, rs_filter filter, INDEX * idx)
{
	if(rec->flag == 1)
		return 0;
	if((filter.type & rec->type) == 0)
		return 0;
	if(rec->artist[0] == 0)
		return 0;
	if(is_artist_in_file(rec->artist, filter.like))
		return 0;

	memcpy(idx->name, rec->artist, sizeof(rec->artist));
	idx->used = 0;
	idx->reserved = 4;
	idx->total = 4;
	idx->offset = 0;

	return 1;
}
int build_artist_field()
{
	int i;
	int res = 0;
	unsigned int br;
	INDEX idx = {"",0,4,4,0};
	rs_filter filter = {0, MEDIA_HI_AUDIO, (int)f_size(hDB->f_index)};

	hDB->index_field[5].offset = (int)f_size(hDB->f_index);
	
	res += f_lseek(hDB->f_index, f_size(hDB->f_index));

	hDB->index_field[5].used = _build_field_(cb_artist_field, filter);	if(hDB->state != 3)return res;
	hDB->index_field[5].reserved = 4;
	hDB->index_field[5].total = hDB->index_field[5].used + hDB->index_field[5].reserved;

	for(i=0; i<hDB->index_field[5].reserved; i++)
	{
		sprintf(idx.name, "artist reserved %d", i);
		res += f_write(hDB->f_index, &idx, sizeof(INDEX), &br);
	}
	return res;
}

int _build_index_id_(cb_filter cb, rs_filter filter)
{
	int res = 0;
	unsigned int br = sizeof(RECORD);
	RECORD rec;
	int id = 0;
	int cnt=0;
	res += f_lseek(hDB->f_record, 0);
	while(res == FR_OK && br == sizeof(RECORD))
	{
		res += message_pump(hDB->state);	if(res)break;if(hDB->state != 3)break;

		id = (int)f_tell(hDB->f_record);
		res += f_read(hDB->f_record, &rec, sizeof(RECORD), &br);
		if(res == FR_OK && br == sizeof(RECORD))
		{
			if(cb(&rec, filter, 0))
			{
				hDB->idbuf[cnt++] = id;
			}
		}
	}
	return cnt;
}

int cb_type_index_id(const RECORD * rec, rs_filter filter, INDEX * idx)
{
	assert(idx == 0);
	if(rec->flag == 1)
		return 0;
	if((filter.type & rec->type) == 0)
		return 0;
	return 1;
}
int build_type_index_id(int type, INDEX * idx)
{
	int i;
	int res = 0;
	unsigned int bw;
	rs_filter filter = {0, type, 0};

	idx->offset = (int)f_size(hDB->f_index);

	idx->used = _build_index_id_(cb_type_index_id, filter);	if(hDB->state != 3)return res;
	idx->total = idx->used + idx->reserved;

	for(i=0; i<idx->reserved; i++)
	{
		hDB->idbuf[idx->used + i] = 0;
	}

	res += f_lseek(hDB->f_index, idx->offset);
	res += f_write(hDB->f_index, hDB->idbuf, sizeof(int)* idx->total, &bw);
	return res;
}
int cb_like_index_id(const RECORD * rec, rs_filter filter, INDEX * idx)
{
	assert(idx == 0);
	if(rec->flag == 1)
		return 0;
	if((filter.type & rec->type) == 0)
		return 0;
	if((filter.like & rec->like) == 0)
		return 0;
	return 1;
}
int build_like_index_id(int like, INDEX * idx)
{
	int i;
	int res = 0;
	unsigned int bw;
	rs_filter filter = {0, MEDIA_HI_AUDIO, (1<<like)};
	assert(like>=0 && like<32);

	idx->offset = (int)f_size(hDB->f_index);

	idx->used = _build_index_id_(cb_like_index_id, filter);	if(hDB->state != 3)return res;
	idx->total = idx->used + idx->reserved;

	for (i = 0; i < idx->reserved; i++)
	{
		hDB->idbuf[idx->used + i] = 0;
	}
	res += f_lseek(hDB->f_index, idx->offset);
	res += f_write(hDB->f_index, hDB->idbuf, sizeof(int) * idx->total, &bw);
	return res;
}
int cb_folder_index_id(const RECORD * rec, rs_filter filter, INDEX * idx)
{
	char rec_dir[MAXPATH];
	split_path(rec->path, rec_dir, 0, 0, 0);
	assert(idx == 0);
	if(rec->flag == 1)
		return 0;
	if((filter.type & rec->type) == 0)
		return 0;
	return 0==dircmp(rec_dir, (char*)filter.p);
}
int build_folder_index_id(INDEX * idx)
{
	int i;
	int res = 0;
	unsigned int bw;
	rs_filter filter = {idx->name, MEDIA_ALL, 0};
	assert(idx->name[0]);

	idx->offset = (int)f_size(hDB->f_index);

	idx->used = _build_index_id_(cb_folder_index_id, filter);	if(hDB->state != 3)return res;
	idx->total = idx->used + idx->reserved;

	for (i = 0; i < idx->reserved; i++)
	{
		hDB->idbuf[idx->used + i] = 0;
	}
	res += f_lseek(hDB->f_index, idx->offset);
	res += f_write(hDB->f_index, hDB->idbuf, sizeof(int) * idx->total, &bw);
	return res;
}
int build_pl_index_id(INDEX * idx)
{
	int i;
	int res = 0;
	unsigned int bw;
	rs_filter filter = {idx->name, MEDIA_HI_AUDIO|MEDIA_HI_WAVE, 0};
	assert(idx->name[0]);

	idx->offset = (int)f_size(hDB->f_index);

	idx->used = _build_index_id_(cb_folder_index_id, filter);	if(hDB->state != 3)return res;
	idx->total = idx->used + idx->reserved;

	for (i = 0; i < idx->reserved; i++)
	{
		hDB->idbuf[idx->used + i] = 0;
	}
	res += f_lseek(hDB->f_index, idx->offset);
	res += f_write(hDB->f_index, hDB->idbuf, sizeof(int) * idx->total, &bw);
	return res;
}
int cb_album_index_id(const RECORD * rec, rs_filter filter, INDEX * idx)
{
	assert(idx == 0);
	if(rec->flag == 1)
		return 0;
	if((filter.type & rec->type) == 0)
		return 0;
	if(strcmp(rec->album, (char*)filter.p) != 0)//memcmp
		return 0;
	return 1;
}
int build_album_index_id(INDEX * idx)
{
	int i;
	int res = 0;
	unsigned int bw;
	rs_filter filter = {idx->name, MEDIA_HI_AUDIO, 0};
	assert(idx->name[0]);

	idx->offset = (int)f_size(hDB->f_index);

	idx->used = _build_index_id_(cb_album_index_id, filter);	if(hDB->state != 3)return res;
	idx->total = idx->used + idx->reserved;

	for (i = 0; i < idx->reserved; i++)
	{
		hDB->idbuf[idx->used + i] = 0;
	}
	res += f_lseek(hDB->f_index, idx->offset);
	res += f_write(hDB->f_index, hDB->idbuf, sizeof(int) * idx->total, &bw);
	return res;
}
int cb_artist_index_id(const RECORD * rec, rs_filter filter, INDEX * idx)
{
	assert(idx == 0);
	if(rec->flag == 1)
		return 0;
	if((filter.type & rec->type) == 0)
		return 0;
	if(strcmp(rec->artist, (char*)filter.p) != 0)//memcmp
		return 0;
	return 1;
}
int build_artist_index_id(INDEX * idx)
{
	int i;
	int res = 0;
	unsigned int bw;
	rs_filter filter = {idx->name, MEDIA_HI_AUDIO, 0};
	assert(idx->name[0]);

	idx->offset = (int)f_size(hDB->f_index);

	idx->used = _build_index_id_(cb_artist_index_id, filter);	if(hDB->state != 3)return res;
	idx->total = idx->used + idx->reserved;

	for (i = 0; i < idx->reserved; i++)
	{
		hDB->idbuf[idx->used + i] = 0;
	}
	res += f_lseek(hDB->f_index, idx->offset);
	res += f_write(hDB->f_index, hDB->idbuf, sizeof(int) * idx->total, &bw);
	return res;
}

int build_type_index()
{
	int i;
	int res = 0;
	unsigned int br;
	INDEX idx = {0};
	const int type[5] = {MEDIA_HI_TEXT, MEDIA_HI_IMAGE, MEDIA_HI_AUDIO, MEDIA_HI_VIDEO, MEDIA_HI_WAVE};
	int used = hDB->index_field[0].used;
	int offset = hDB->index_field[0].offset;

	assert(5 == used);

	for(i=0; i<used; i++)
	{
		if(i == used/2)	hDB->cb(-555, 11);
		res += f_lseek(hDB->f_index, offset + i * sizeof(INDEX));	if(res)break;
		res += f_read(hDB->f_index, &idx, sizeof(INDEX), &br);		if(res)break;
		res += build_type_index_id(type[i], &idx);					if(res)break;if(hDB->state != 3)break;
		res += f_lseek(hDB->f_index, offset + i * sizeof(INDEX));	if(res)break;
		res += f_write(hDB->f_index, &idx, sizeof(INDEX), &br);		if(res)break;
	}
	return res;
}
int build_like_index()
{
	int i;
	int res = 0;
	unsigned int br;
	INDEX idx = {0};
	int used = hDB->index_field[1].used;
	int offset = hDB->index_field[1].offset;

	assert(32 == used);

	for(i=0; i<used; i++)
	{
		if(i == used/2)	hDB->cb(-555, 13);
		res += f_lseek(hDB->f_index, offset + i * sizeof(INDEX));	if(res)break;
		res += f_read(hDB->f_index, &idx, sizeof(INDEX), &br);		if(res)break;
		res += build_like_index_id(i, &idx);						if(res)break;if(hDB->state != 3)break;
		res += f_lseek(hDB->f_index, offset + i * sizeof(INDEX));	if(res)break;
		res += f_write(hDB->f_index, &idx, sizeof(INDEX), &br);		if(res)break;
	}
	return res;
}
int build_folder_index()
{
	int i;
	int res = 0;
	unsigned int br;
	INDEX idx = {0};
	int used = hDB->index_field[2].used;
	int offset = hDB->index_field[2].offset;

	//assert(? == used);

	for(i=0; i<used; i++)
	{
		if(i == used/2)	hDB->cb(-555, 15);
		res += f_lseek(hDB->f_index, offset + i * sizeof(INDEX));	if(res)break;
		res += f_read(hDB->f_index, &idx, sizeof(INDEX), &br);		if(res)break;
		res += build_folder_index_id(&idx);							if(res)break;if(hDB->state != 3)break;
		res += f_lseek(hDB->f_index, offset + i * sizeof(INDEX));	if(res)break;
		res += f_write(hDB->f_index, &idx, sizeof(INDEX), &br);		if(res)break;
	}
	return res;
}
int build_pl_index()
{
	int i;
	int res = 0;
	unsigned int br;
	INDEX idx = {0};
	int used = hDB->index_field[3].used;
	int offset = hDB->index_field[3].offset;

	//assert(? == used);

	for(i=0; i<used; i++)
	{
		if(i == used/2)	hDB->cb(-555, 17);
		res += f_lseek(hDB->f_index, offset + i * sizeof(INDEX));	if(res)break;
		res += f_read(hDB->f_index, &idx, sizeof(INDEX), &br);		if(res)break;
		res += build_pl_index_id(&idx);								if(res)break;if(hDB->state != 3)break;
		res += f_lseek(hDB->f_index, offset + i * sizeof(INDEX));	if(res)break;
		res += f_write(hDB->f_index, &idx, sizeof(INDEX), &br);		if(res)break;
	}
	return res;
}
int build_album_index()
{
	int i;
	int res = 0;
	unsigned int br;
	INDEX idx = {0};
	int used = hDB->index_field[4].used;
	int offset = hDB->index_field[4].offset;

	//assert(? == used);

	for(i=0; i<used; i++)
	{
		hDB->cb(-555, 18 + i*42/used);//[18,60]
		res += f_lseek(hDB->f_index, offset + i * sizeof(INDEX));	if(res)break;
		res += f_read(hDB->f_index, &idx, sizeof(INDEX), &br);		if(res)break;
		res += build_album_index_id(&idx);							if(res)break;if(hDB->state != 3)break;
		res += f_lseek(hDB->f_index, offset + i * sizeof(INDEX));	if(res)break;
		res += f_write(hDB->f_index, &idx, sizeof(INDEX), &br);		if(res)break;
	}
	return res;
}
int build_artist_index()
{
	int i;
	int res = 0;
	unsigned int br;
	INDEX idx = {0};
	int used = hDB->index_field[5].used;
	int offset = hDB->index_field[5].offset;

	//assert(? == used);

	for(i=0; i<used; i++)
	{
		hDB->cb(-555, 60 + i*40/used);//[60,100]
		res += f_lseek(hDB->f_index, offset + i * sizeof(INDEX));	if(res)break;
		res += f_read(hDB->f_index, &idx, sizeof(INDEX), &br);		if(res)break;
		res += build_artist_index_id(&idx);							if(res)break;if(hDB->state != 3)break;
		res += f_lseek(hDB->f_index, offset + i * sizeof(INDEX));	if(res)break;
		res += f_write(hDB->f_index, &idx, sizeof(INDEX), &br);		if(res)break;
	}
	return res;
}

int build_index(void)
{
	int res = 0;

	res += build_type_field();	hDB->cb(hDB->state, -1);if(res)return res;if(hDB->state != 3)return res;  hDB->cb(-555, 1);
	res += build_like_field();	hDB->cb(hDB->state, -2);if(res)return res;if(hDB->state != 3)return res;  hDB->cb(-555, 2);
	res += build_folder_field();hDB->cb(hDB->state, -3);if(res)return res;if(hDB->state != 3)return res;  hDB->cb(-555, 3);
	res += build_pl_field();	hDB->cb(hDB->state, -4);if(res)return res;if(hDB->state != 3)return res;  hDB->cb(-555, 4);
	res += build_album_field();	hDB->cb(hDB->state, -5);if(res)return res;if(hDB->state != 3)return res;  hDB->cb(-555, 7);
	res += build_artist_field();hDB->cb(hDB->state, -6);if(res)return res;if(hDB->state != 3)return res;  hDB->cb(-555, 10);
	
	res += build_type_index();	hDB->cb(hDB->state, -7);if(res)return res;if(hDB->state != 3)return res;  hDB->cb(-555, 12);
	res += build_like_index();	hDB->cb(hDB->state, -8);if(res)return res;if(hDB->state != 3)return res;  hDB->cb(-555, 14);
	res += build_folder_index();hDB->cb(hDB->state, -9);if(res)return res;if(hDB->state != 3)return res;  hDB->cb(-555, 16);
	res += build_pl_index();	hDB->cb(hDB->state, -10);if(res)return res;if(hDB->state != 3)return res; hDB->cb(-555, 18);
	res += build_album_index();	hDB->cb(hDB->state, -11);if(res)return res;if(hDB->state != 3)return res; hDB->cb(-555, 60);
	res += build_artist_index();hDB->cb(hDB->state, -12);if(res)return res;if(hDB->state != 3)return res; hDB->cb(-555, 100);

	return res;
}

int add_recid_(const int seek, int recid)
{
	int i;
	int res = 0;
	unsigned int br;
	INDEX idx = {0};

	assert(seek % sizeof(INDEX) == 0);
	res += f_lseek(hDB->f_index, seek);							if(res)return res;
	res += f_read(hDB->f_index, &idx, sizeof(INDEX), &br);		if(res)return res;

	res += f_lseek(hDB->f_index, idx.offset);					if(res)return res;
	for(i=0; i<idx.used; i++)
	{
		int tmpid;
		res += f_read(hDB->f_index, &tmpid, sizeof(int), &br);	if(res)return res;
		if(tmpid == recid) return res;	//已经存在，不用追加
	}

	assert(idx.reserved > 0);
	assert(idx.used + idx.reserved == idx.total);

	if(idx.reserved > 0)
	{
		res += f_lseek(hDB->f_index, idx.offset + idx.used * sizeof(int));	if(res)return res;
		res += f_write(hDB->f_index, &recid, sizeof(int), &br);				if(res)return res;

		idx.used ++;
		idx.reserved --;

		res += f_lseek(hDB->f_index, seek);									if(res)return res;
		res += f_write(hDB->f_index, &idx, sizeof(INDEX), &br);				if(res)return res;
		res += f_sync(hDB->f_index);										if(res)return res;
	}
	return res;
}
int del_recid_(const int seek, int recid)
{
	int i;
	int res = 0;
	unsigned int br;
	INDEX idx = {0};

	assert(seek % sizeof(INDEX) == 0);
	res += f_lseek(hDB->f_index, seek);							if(res)return res;
	res += f_read(hDB->f_index, &idx, sizeof(INDEX), &br);		if(res)return res;

	res += f_lseek(hDB->f_index, idx.offset);					if(res)return res;
	for(i=0; i<idx.used; i++)
	{
		int tmpid;
		res += f_read(hDB->f_index, &tmpid, sizeof(int), &br);	if(res)return res;
		if(tmpid == recid)
		{
			res += f_lseek(hDB->f_index, idx.offset + sizeof(int)*(idx.used-1));	if(res)return res;
			res += f_read(hDB->f_index, &tmpid, sizeof(int), &br);					if(res)return res;
			res += f_lseek(hDB->f_index, idx.offset + sizeof(int)*i);				if(res)return res;
			res += f_write(hDB->f_index, &tmpid, sizeof(int), &br);					if(res)return res;

			idx.used --;
			idx.reserved ++;

			res += f_lseek(hDB->f_index, seek);									if(res)return res;
			res += f_write(hDB->f_index, &idx, sizeof(INDEX), &br);				if(res)return res;
			res += f_sync(hDB->f_index);										if(res)return res;
			return res;
		}
	}

	return res;
}
int get_recid_(const int seek, int offset, int * recid, int * cnt)
{
	int res = 0;
	unsigned int br;
	INDEX idx = {0};
	int in_cnt = *cnt;
	int has_cnt = 0;

	*cnt = 0;

	assert(seek % sizeof(INDEX) == 0);
	res += f_lseek(hDB->f_index, seek);							if(res){*cnt=-1;return res;}
	res += f_read(hDB->f_index, &idx, sizeof(INDEX), &br);		if(res){*cnt=-1;return res;}

	res += f_lseek(hDB->f_index, idx.offset + offset*sizeof(int));	if(res){*cnt=-1;return res;}
	has_cnt = idx.used > offset ? idx.used - offset : 0;
	(*cnt) = has_cnt < in_cnt ? has_cnt : in_cnt;
	res += f_read(hDB->f_index, recid, sizeof(int)*(*cnt), &br);	if(res){*cnt=-1;return res;}

	return res;
}

int seek_type_(int type)
{
	int seek = hDB->index_field[0].offset;
	switch(type)
	{
	case MEDIA_HI_TEXT : seek += sizeof(INDEX) * 0; break;
	case MEDIA_HI_IMAGE: seek += sizeof(INDEX) * 1; break;
	case MEDIA_HI_AUDIO: seek += sizeof(INDEX) * 2; break;
	case MEDIA_HI_VIDEO: seek += sizeof(INDEX) * 3; break;
	case MEDIA_HI_WAVE : seek += sizeof(INDEX) * 4; break;
	default: assert(0);	seek = -1;					break;
	}
	return seek;
}
int seek_like_(int like)
{
	int seek = hDB->index_field[1].offset;
	if(like < -32 || like == 0 || like > 32)
	{
		assert(0);
		return -1;
	}
	seek += sizeof(INDEX) * (like-1);
	return seek;
}
int seek_folder_(char* folder)
{
	int i;
	int res = 0;
	unsigned int br;
	INDEX idx = {0};
	int seek = hDB->index_field[2].offset;
	assert(seek % sizeof(INDEX) == 0);

	res += f_lseek(hDB->f_index, seek);						if(res)return -1;
	for(i=0; i<hDB->index_field[2].used; i++)
	{
		res += f_read(hDB->f_index, &idx, sizeof(INDEX), &br);	if(res)return -1;
		if(dircmp(idx.name, folder) == 0)
		{
			return (int)f_tell(hDB->f_index)-sizeof(INDEX);
		}
	}

	return -1;
}
int seek_pl_(char* folder)
{
	int i;
	int res = 0;
	unsigned int br;
	INDEX idx = {0};
	int seek = hDB->index_field[3].offset;
	assert(seek % sizeof(INDEX) == 0);

	res += f_lseek(hDB->f_index, seek);						if(res)return -1;
	for(i=0; i<hDB->index_field[3].used; i++)
	{
		res += f_read(hDB->f_index, &idx, sizeof(INDEX), &br);	if(res)return -1;
		if(dircmp(idx.name, folder) == 0)
		{
			return (int)f_tell(hDB->f_index)-sizeof(INDEX);
		}
	}

	return -1;
}
int seek_album_(char* album)
{
	int i;
	int res = 0;
	unsigned int br;
	INDEX idx = {0};
	int seek = hDB->index_field[4].offset;
	assert(seek % sizeof(INDEX) == 0);

	res += f_lseek(hDB->f_index, seek);						if(res)return -1;
	for(i=0; i<hDB->index_field[4].used; i++)
	{
		res += f_read(hDB->f_index, &idx, sizeof(INDEX), &br);	if(res)return -1;
		if(strcmp(idx.name, album) == 0)
		{
			return (int)f_tell(hDB->f_index)-sizeof(INDEX);
		}
	}

	return -1;
}
int seek_artist_(char* artist)
{
	int i;
	int res = 0;
	unsigned int br;
	INDEX idx = {0};
	int seek = hDB->index_field[5].offset;
	assert(seek % sizeof(INDEX) == 0);

	res += f_lseek(hDB->f_index, seek);						if(res)return -1;
	for(i=0; i<hDB->index_field[5].used; i++)
	{
		res += f_read(hDB->f_index, &idx, sizeof(INDEX), &br);	if(res)return -1;
		if(strcmp(idx.name, artist) == 0)
		{
			return (int)f_tell(hDB->f_index)-sizeof(INDEX);
		}
	}

	return -1;
}

int add_type_recid(int type, int recid)
{
	int seek = seek_type_(type);
	if(seek != -1)
		return add_recid_(seek, recid);
	else
		return -1;
}
int add_like_recid(int like, int recid)
{
	int seek = seek_like_(like);
	if(seek != -1)
		return add_recid_(seek, recid);
	else
		return -1;
}
int add_folder_recid(char* folder, int recid)
{
	int seek = seek_folder_(folder);
	if(seek != -1)
		return add_recid_(seek, recid);
	else
		return -1;
}
int add_pl_recid(char* folder, int recid)
{
	int seek = seek_pl_(folder);
	if(seek != -1)
		return add_recid_(seek, recid);
	else
		return -1;
}
int add_album_recid(char* album, int recid)
{
	int seek = seek_album_(album);
	if(seek != -1)
		return add_recid_(seek, recid);
	else
		return -1;
}
int add_artist_recid(char* artist, int recid)
{
	int seek = seek_album_(artist);
	if(seek != -1)
		return add_recid_(seek, recid);
	else
		return -1;
}

int del_type_recid(int type, int recid)
{
	int seek = seek_type_(type);
	if(seek != -1)
		return del_recid_(seek, recid);
	else
		return -1;
}
int del_like_recid(int like, int recid)
{
	int seek = seek_like_(like);
	if(seek != -1)
		return del_recid_(seek, recid);
	else
		return -1;
}
int del_folder_recid(char* folder, int recid)
{
	int seek = seek_folder_(folder);
	if(seek != -1)
		return del_recid_(seek, recid);
	else
		return -1;
}
int del_pl_recid(char* folder, int recid)
{
	int seek = seek_pl_(folder);
	if(seek != -1)
		return del_recid_(seek, recid);
	else
		return -1;
}
int del_album_recid(char* album, int recid)
{
	int seek = seek_album_(album);
	if(seek != -1)
		return del_recid_(seek, recid);
	else
		return -1;
}
int del_artist_recid(char* artist, int recid)
{
	int seek = seek_artist_(artist);
	if(seek != -1)
		return del_recid_(seek, recid);
	else
		return -1;
}

int get_type_recid(int type, int offset, int * recid, int * cnt)
{
	int seek = seek_type_(type);
	if(seek != -1)
		return get_recid_(seek, offset, recid, cnt);
	else
		return -1;
}
int get_like_recid(int like, int offset, int * recid, int * cnt)
{
	int seek = seek_like_(like);
	if(seek != -1)
		return get_recid_(seek, offset, recid, cnt);
	else
		return -1;
}
int get_folder_recid(char* folder, int offset, int * recid, int * cnt)
{
	int seek = seek_folder_(folder);
	if(seek != -1)
		return get_recid_(seek, offset, recid, cnt);
	else
		return -1;
}
int get_pl_recid(char* folder, int offset, int * recid, int * cnt)
{
	int seek = seek_pl_(folder);
	if(seek != -1)
		return get_recid_(seek, offset, recid, cnt);
	else
		return -1;
}
int get_album_recid(char* album, int offset, int * recid, int * cnt)
{
	int seek = seek_album_(album);
	if(seek != -1)
		return get_recid_(seek, offset, recid, cnt);
	else
		return -1;
}
int get_artist_recid(char* artist, int offset, int * recid, int * cnt)
{
	int seek = seek_artist_(artist);
	if(seek != -1)
		return get_recid_(seek, offset, recid, cnt);
	else
		return -1;
}

int get_type_index(int type, INDEX * idx)
{
	int res = 0;
	unsigned int br;
	int seek = seek_type_(type);
	if(seek == -1)
	{
		return -1;
	}
	assert(seek % sizeof(INDEX) == 0);
	res += f_lseek(hDB->f_index, seek);
	res += f_read(hDB->f_index, idx, sizeof(INDEX), &br);
	return res;
}

int get_like_index(int like, INDEX * idx)
{
	int res = 0;
	unsigned int br;
	int seek = seek_like_(like);
	if(seek == -1)
	{
		return -1;
	}
	assert(seek % sizeof(INDEX) == 0);
	res += f_lseek(hDB->f_index, seek);
	res += f_read(hDB->f_index, idx, sizeof(INDEX), &br);
	return res;
}

int get_folder_index(char* folder, INDEX * idx)
{
	int res = 0;
	unsigned int br;
	int seek = seek_folder_(folder);
	if(seek == -1)
	{
		return -1;
	}
	assert(seek % sizeof(INDEX) == 0);
	res += f_lseek(hDB->f_index, seek);
	res += f_read(hDB->f_index, idx, sizeof(INDEX), &br);
	return res;
}

int get_pl_index(char* folder, INDEX * idx)
{
	int res = 0;
	unsigned int br;
	int seek = seek_pl_(folder);
	if(seek == -1)
	{
		return -1;
	}
	assert(seek % sizeof(INDEX) == 0);
	res += f_lseek(hDB->f_index, seek);
	res += f_read(hDB->f_index, idx, sizeof(INDEX), &br);
	return res;
}

int get_album_index(char* album, INDEX * idx)
{
	int res = 0;
	unsigned int br;
	int seek = seek_album_(album);
	if(seek == -1)
	{
		return -1;
	}
	assert(seek % sizeof(INDEX) == 0);
	res += f_lseek(hDB->f_index, seek);
	res += f_read(hDB->f_index, idx, sizeof(INDEX), &br);
	return res;
}

int get_artist_index(char* artist, INDEX * idx)
{
	int res = 0;
	unsigned int br;
	int seek = seek_artist_(artist);
	if(seek == -1)
	{
		return -1;
	}
	assert(seek % sizeof(INDEX) == 0);
	res += f_lseek(hDB->f_index, seek);
	res += f_read(hDB->f_index, idx, sizeof(INDEX), &br);
	return res;
}
